// ignore_for_file: library_private_types_in_public_api

import 'dart:math';

import 'package:extended_image/extended_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_smart_heating/common/app.dart';
import 'package:flutter_smart_heating/ui/ui.dart';
import 'package:get/get.dart';

import 'package:image_gallery_saver/image_gallery_saver.dart';

Future<bool> saveNetworkImageToPhoto(String url, {bool useCache = true}) async {
  var data = await getNetworkImageData(url, useCache: useCache);
  final result = await ImageGallerySaver.saveImage(data!, quality: 100);
  if (result['isSuccess']) {
    Ui.toast("Saved".tr);
  } else {
    Ui.toast("Save Failed".tr);
  }
  return result;
}

/// make hero better when slide out
class HeroWidget extends StatefulWidget {
  const HeroWidget({
    super.key,
    required this.child,
    required this.tag,
    required this.slidePagekey,
    this.slideType = SlideType.onlyImage,
  });
  final Widget child;
  final SlideType slideType;
  final Object tag;
  final GlobalKey<ExtendedImageSlidePageState> slidePagekey;
  @override
  _HeroWidgetState createState() => _HeroWidgetState();
}

class _HeroWidgetState extends State<HeroWidget> {
  RectTween? _rectTween;
  @override
  Widget build(BuildContext context) {
    return Hero(
      tag: widget.tag,
      createRectTween: (Rect? begin, Rect? end) {
        _rectTween = RectTween(begin: begin, end: end);
        return _rectTween!;
      },
      // make hero better when slide out
      flightShuttleBuilder: (BuildContext flightContext,
          Animation<double> animation,
          HeroFlightDirection flightDirection,
          BuildContext fromHeroContext,
          BuildContext toHeroContext) {
        // make hero more smoothly
        final Hero hero = (flightDirection == HeroFlightDirection.pop
            ? fromHeroContext.widget
            : toHeroContext.widget) as Hero;
        if (_rectTween == null) {
          return hero;
        }

        if (flightDirection == HeroFlightDirection.pop) {
          final bool fixTransform = widget.slideType == SlideType.onlyImage &&
              (widget.slidePagekey.currentState!.offset != Offset.zero ||
                  widget.slidePagekey.currentState!.scale != 1.0);

          final Widget toHeroWidget = (toHeroContext.widget as Hero).child;
          return AnimatedBuilder(
            animation: animation,
            builder: (BuildContext buildContext, Widget? child) {
              Widget animatedBuilderChild = hero.child;

              // make hero more smoothly
              animatedBuilderChild = Stack(
                clipBehavior: Clip.antiAlias,
                alignment: Alignment.center,
                children: <Widget>[
                  Opacity(
                    opacity: 1 - animation.value,
                    child: UnconstrainedBox(
                      child: SizedBox(
                        width: _rectTween!.begin!.width,
                        height: _rectTween!.begin!.height,
                        child: toHeroWidget,
                      ),
                    ),
                  ),
                  Opacity(
                    opacity: animation.value,
                    child: animatedBuilderChild,
                  )
                ],
              );

              // fix transform when slide out
              if (fixTransform) {
                final Tween<Offset> offsetTween = Tween<Offset>(
                    begin: Offset.zero,
                    end: widget.slidePagekey.currentState!.offset);

                final Tween<double> scaleTween = Tween<double>(
                    begin: 1.0, end: widget.slidePagekey.currentState!.scale);
                animatedBuilderChild = Transform.translate(
                  offset: offsetTween.evaluate(animation),
                  child: Transform.scale(
                    scale: scaleTween.evaluate(animation),
                    child: animatedBuilderChild,
                  ),
                );
              }

              return animatedBuilderChild;
            },
          );
        }
        return hero.child;
      },
      child: widget.child,
    );
  }
}

class ImagePreview extends StatefulWidget {
  const ImagePreview({
    super.key,
    this.url,
    this.title = '',
    this.allowToSave = true,
    this.allowToEdit = false,
  });
  final dynamic url;
  final String title;
  final bool allowToSave;
  final bool allowToEdit;

  static Future show(
    context, {
    dynamic url,
    String title = '',
    bool allowToSave = true,
  }) async {
    return Navigator.of(context).push(
      PageRouteBuilder(
        opaque: false,
        pageBuilder: (_, __, ___) => ImagePreview(
          url: url,
          title: title,
          allowToSave: allowToSave,
        ),
      ),
    );
  }

  @override
  _ImagePreviewState createState() => _ImagePreviewState();
}

class _ImagePreviewState extends State<ImagePreview> {
  GlobalKey<ExtendedImageSlidePageState> slidePagekey =
      GlobalKey<ExtendedImageSlidePageState>();
  double appbarOpacity = 1;
  bool imageLoadingFailed = false;

  @override
  void initState() {
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.transparent,
      extendBodyBehindAppBar: true,
      appBar: AppBar(
        elevation: 0,
        title: Text(
          widget.title,
          style: TextStyle(
            color: Colors.white.withOpacity(appbarOpacity),
            shadows: [
              Shadow(
                color: Colors.black26.withOpacity(appbarOpacity),
                blurRadius: 5,
              ),
            ],
          ),
        ),
        leading: const CloseButton(),
        backgroundColor: Colors.black.withOpacity(0),
        foregroundColor: Colors.white.withOpacity(appbarOpacity),
        actions: [
          if (widget.allowToSave)
            IconButton(
              onPressed: () {
                Get.bottomSheet(menuView(Get.context));
              },
              icon: const Icon(Icons.more_horiz),
            )
        ],
      ),
      body: SizedBox(
        width: double.infinity,
        height: double.infinity,
        child: ExtendedImageSlidePage(
          key: slidePagekey,
          slideAxis: SlideAxis.both,
          slideType: SlideType.wholePage,
          onSlidingPage: (state) {
            setState(() {
              appbarOpacity;
            });
          },
          slidePageBackgroundHandler: (offset, pageSize) {
            double opacity = offset.distance /
                (Offset(pageSize.width, pageSize.height).distance / 2.0);
            opacity = min(1, max(1 - opacity, 0));
            appbarOpacity = opacity > 0.8 ? opacity : 0;

            return Colors.black.withOpacity(opacity);
          },
          child: GestureDetector(
            child: HeroWidget(
              tag: widget.url.toString(),
              slideType: SlideType.wholePage,
              slidePagekey: slidePagekey,
              child: widget.url.runtimeType == String
                  ? ExtendedImage.network(
                      widget.url,
                      mode: ExtendedImageMode.gesture,
                      enableSlideOutPage: true,
                      heroBuilderForSlidingPage: (widget) {
                        return widget;
                      },
                      loadStateChanged: (state) {
                        return imageLoadStateView(state);
                      },
                    )
                  : ExtendedImage.file(
                      widget.url,
                      mode: ExtendedImageMode.gesture,
                      enableSlideOutPage: true,
                      heroBuilderForSlidingPage: (widget) {
                        return widget;
                      },
                      loadStateChanged: (state) {
                        return imageLoadStateView(state);
                      },
                    ),
            ),
            onTap: () {
              setState(() {
                appbarOpacity = 0;
              });
              slidePagekey.currentState!.popPage();
              Navigator.pop(context);
            },
            onLongPress: () {
              App.hapticFeedback();
              Get.bottomSheet(menuView(Get.context));
            },
          ),
        ),
      ),
    );
  }

  Widget? imageLoadStateView(ExtendedImageState state) {
    if (state.extendedImageLoadState == LoadState.loading) {
      return const Center(
        child: CupertinoActivityIndicator(
          color: Colors.white,
          animating: true,
          radius: 12.0,
        ),
      );
    } else if (state.extendedImageLoadState == LoadState.failed) {
      imageLoadingFailed = true;
      return const Center(
        child: Text(
          '图片加载失败',
          style: TextStyle(color: Colors.white),
        ),
      );
    } else {
      return null;
    }
  }

  Widget menuView(context) {
    return UiActionSheet(
      title: '更多操作',
      items: [
        UiActionSheetItemData(
          title: '保存图片',
          value: 'save',
          disabled: imageLoadingFailed || !widget.allowToSave,
        ),
      ],
      onTap: (value) async {
        switch (value) {
          case 'save':
            saveNetworkImageToPhoto(widget.url!);
            break;
        }
      },
    );
  }
}
